package com.cloudshop.service.common.utils;

import com.cloudshop.service.common.enums.JwtKeyEnum;
import com.cloudshop.service.common.exception.LoginException;
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.ExpiredJwtException;
import io.jsonwebtoken.JwtBuilder;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import java.util.Date;
import java.util.List;

/**
 * Jwt工具类.
 *
 * @author 宫新程
 * @since 2019/4/1 9:46
 */
public class JwtTokenUtil {

  private static final ThreadLocal<String> tokenThread = new ThreadLocal<>();

  private static final String TOKEN_SALT = "R29uZ1hpbmNoZW5n"; // 盐：GongXincheng
  private static final long TOKEN_TTL = 3600000L; // token过期时间

  /**
   * 生成token.
   *
   * @param userId 用户id
   * @param userName 用户名
   * @param nickName 用户昵称
   * @param shopId 店铺id
   * @param shopName 店铺名称
   * @param roleList 角色列表
   * @param permissionCodeList 权限列表
   * @param permissionNameList 权限列表
   * @return token/get-user-info-by-token
   */
  public static String createToken(
      Integer userId,
      String userName,
      String nickName,
      Integer shopId,
      String shopName,
      List<String> roleList,
      List<String> permissionCodeList,
      List<String> permissionNameList) {

    long nowMillis = System.currentTimeMillis();
    Date now = new Date(nowMillis);
    JwtBuilder jwtBuilder =
        Jwts.builder()
            .setIssuedAt(now)
            .setExpiration(new Date(nowMillis + TOKEN_TTL))
            .signWith(SignatureAlgorithm.HS256, TOKEN_SALT)
            .claim(JwtKeyEnum.TOKEN_USER_ID.getKey(), userId)
            .claim(JwtKeyEnum.TOKEN_USER_NAME.getKey(), userName)
            .claim(JwtKeyEnum.TOKEN_NICK_NAME.getKey(), nickName)
            .claim(JwtKeyEnum.TOKEN_SHOP_ID.getKey(), shopId)
            .claim(JwtKeyEnum.TOKEN_SHOP_NAME.getKey(), shopName)
            .claim(JwtKeyEnum.TOKEN_ROLE_LIST.getKey(), roleList)
            .claim(JwtKeyEnum.TOKEN_PERMISSION_CODE_LIST.getKey(), permissionCodeList)
            .claim(JwtKeyEnum.TOKEN_PERMISSION_NAME_LIST.getKey(), permissionNameList);
    return jwtBuilder.compact();
  }

  /**
   * 解析JWT.
   *
   * @param token token串
   * @return Claims
   */
  private static Claims parseJwt(String token) {
    try {
      return Jwts.parser().setSigningKey(TOKEN_SALT).parseClaimsJws(token).getBody();
    } catch (ExpiredJwtException e) {
      throw new RuntimeException("token已过期, 请重新获取");
    } catch (Exception e) {
      throw new RuntimeException("Token Error !");
    }
  }

  /** 获取token 串. */
  public static String getToken() {
    String token = tokenThread.get();
    if (CheckEmptyUtil.isEmpty(token)) {
      throw new LoginException("未登录");
    }
    if (!token.startsWith(JwtKeyEnum.TOKEN_PREFIX.getKey())) {
      throw new LoginException("Token Error !");
    }
    return token.replace(JwtKeyEnum.TOKEN_PREFIX.getKey(), "");
  }

  /**
   * 设置token到ThreadLocal中.
   *
   * @param token token.
   */
  public static void setTokenThread(String token) {
    tokenThread.set(token);
  }

  /**
   * 获取 Claims.
   *
   * @return Claims
   */
  public static Claims getClaims() {
    String token = getToken();
    return parseJwt(token);
  }

  /** 获取UserId. */
  public static Integer getUserId() {
    Claims claims = getClaims();
    return claims.get(JwtKeyEnum.TOKEN_USER_ID.getKey(), Integer.class);
  }

  /** 获取用户名. */
  public static String getUserName() {
    Claims claims = getClaims();
    return claims.get(JwtKeyEnum.TOKEN_USER_NAME.getKey(), String.class);
  }

  /** 获取昵称. */
  public static String getNickName() {
    Claims claims = getClaims();
    return claims.get(JwtKeyEnum.TOKEN_NICK_NAME.getKey(), String.class);
  }

  /** 获取店铺id. */
  public static Integer getShopId() {
    Claims claims = getClaims();
    return claims.get(JwtKeyEnum.TOKEN_SHOP_ID.getKey(), Integer.class);
  }

  /** 获取店铺名称. */
  public static String getShopName() {
    Claims claims = getClaims();
    return claims.get(JwtKeyEnum.TOKEN_SHOP_NAME.getKey(), String.class);
  }

  /** 获取角色集合. */
  public static List getUserRoles() {
    Claims claims = getClaims();
    return claims.get(JwtKeyEnum.TOKEN_ROLE_LIST.getKey(), List.class);
  }

  /** 获取该用户的权限编码集合. */
  public static List getPermissionCodes() {
    Claims claims = getClaims();
    return claims.get(JwtKeyEnum.TOKEN_PERMISSION_CODE_LIST.getKey(), List.class);
  }

  /** 获取该用户的权限编码集合. */
  public static List getPermissionNames() {
    Claims claims = getClaims();
    return claims.get(JwtKeyEnum.TOKEN_PERMISSION_NAME_LIST.getKey(), List.class);
  }
}
